//! 字节码定义和生成器

use crate::vm::Instruction;
use std::collections::HashMap;

/// 字节码结构
#[derive(Debug, Clone, PartialEq)]
pub struct Bytecode {
    pub instructions: Vec<Instruction>,
    pub constants: Vec<i64>,
    pub function_table: HashMap<String, usize>,
}

impl Bytecode {
    /// 从字节数组创建字节码
    pub fn from_bytes(bytes: &[u8]) -> Result<Self, String> {
        // 简化的字节码解析
        let mut instructions = Vec::new();
        let mut i = 0;
        
        while i < bytes.len() {
            let opcode = bytes[i];
            i += 1;
            
            let instruction = match opcode {
                0x01 => {
                    // PushInt
                    if i + 8 <= bytes.len() {
                        let value = i64::from_le_bytes([
                            bytes[i], bytes[i+1], bytes[i+2], bytes[i+3],
                            bytes[i+4], bytes[i+5], bytes[i+6], bytes[i+7]
                        ]);
                        i += 8;
                        Instruction::PushInt(value)
                    } else {
                        return Err("Invalid bytecode: incomplete PushInt".to_string());
                    }
                },
                0x02 => Instruction::Add,
                0x03 => Instruction::Sub,
                0x04 => Instruction::Mul,
                0x05 => Instruction::Div,
                0x06 => Instruction::Load,
                0x07 => Instruction::Store,
                0x08 => Instruction::Call,
                0x09 => Instruction::Ret,
                0x0A => Instruction::Halt,
                _ => return Err(format!("Unknown opcode: {}", opcode)),
            };
            
            instructions.push(instruction);
        }
        
        Ok(Self {
            instructions,
            constants: Vec::new(),
            function_table: HashMap::new(),
        })
    }
    
    /// 创建空字节码
    pub fn new() -> Self {
        Self {
            instructions: Vec::new(),
            constants: Vec::new(),
            function_table: HashMap::new(),
        }
    }
    
    /// 添加指令
    pub fn add_instruction(&mut self, instruction: Instruction) {
        self.instructions.push(instruction);
    }
    
    /// 转换为字节数组
    pub fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::new();
        
        for instruction in &self.instructions {
            match instruction {
                Instruction::PushInt(value) => {
                    bytes.push(0x01);
                    bytes.extend_from_slice(&value.to_le_bytes());
                },
                Instruction::Add => bytes.push(0x02),
                Instruction::Sub => bytes.push(0x03),
                Instruction::Mul => bytes.push(0x04),
                Instruction::Div => bytes.push(0x05),
                Instruction::Load => bytes.push(0x06),
                Instruction::Store => bytes.push(0x07),
                Instruction::Call => bytes.push(0x08),
                Instruction::Ret => bytes.push(0x09),
                Instruction::Halt => bytes.push(0x0A),
            }
        }
        
        bytes
    }
}

/// 字节码指令
#[derive(Debug, Clone, PartialEq)]
pub enum Instruction {
    PushInt(i64),
    Add,
    Sub,
    Mul,
    Div,
    Load,
    Store,
    Call,
    Ret,
    Halt,
}

/// 字节码生成器
pub struct BytecodeGenerator {
    bytecode: Bytecode,
    next_label: usize,
}

impl BytecodeGenerator {
    pub fn new() -> Self {
        Self {
            bytecode: Bytecode::new(),
            next_label: 0,
        }
    }
    
    pub fn push_int(&mut self, value: i64) {
        self.bytecode.add_instruction(Instruction::PushInt(value));
    }
    
    pub fn add(&mut self) {
        self.bytecode.add_instruction(Instruction::Add);
    }
    
    pub fn sub(&mut self) {
        self.bytecode.add_instruction(Instruction::Sub);
    }
    
    pub fn mul(&mut self) {
        self.bytecode.add_instruction(Instruction::Mul);
    }
    
    pub fn div(&mut self) {
        self.bytecode.add_instruction(Instruction::Div);
    }
    
    pub fn ret(&mut self) {
        self.bytecode.add_instruction(Instruction::Ret);
    }
    
    pub fn halt(&mut self) {
        self.bytecode.add_instruction(Instruction::Halt);
    }
    
    pub fn build(self) -> Bytecode {
        self.bytecode
    }
}